﻿using System;
using System.Collections;
using System.Xml;
using System.Xml.Schema;
using System.IO;
using InfoJetSoft.Service.Entity;
using InfoJetSoft.Service.Util;

namespace InfoJetSoft.Service.Worker
{
	class SchemaSetWorker
	{

		public static void buildSchemaSet(Manifest manifest)
		{
			//CID 0231 //2009.02.19 //Begin
			if( System.Environment.Version.Major >= 2 )
			{
				//CID 0422 //2009.10.14 //Begin
				try
				{
					buildSet( manifest );
				}
				catch( XmlSchemaException xse1 )
				{
                    try
					{
						buildCollection2( manifest );
					}
					catch( XmlSchemaException xse2 )
					{
						buildCollection1( manifest );
					}
				}
				//CID 0422 //2009.10.14 //End
			}
			else
			{
				buildCollection1( manifest );
			}
			//CID 0231 //2009.02.19 //End
		}

		//CID 0422 //2009.10.14 //Begin
		private static void buildSet(Manifest manifest)
		{
            try
            {
                //CID 0611 //2010.06.04 //Begin
                XmlSchemaSet schemaSet = new XmlSchemaSet();
                SchemaFileResolver schemaFileResolver = new SchemaFileResolver(manifest);
                schemaSet.XmlResolver = schemaFileResolver;
                SchemaDef rootSchemaDef = manifest.RootSchemaDef;
                schemaSet.Add(rootSchemaDef.Uri, rootSchemaDef.Location);
                foreach (SchemaDef schemaDef in manifest.SchemaDefList)
                {
                    schemaSet.Add(schemaDef.Uri, schemaDef.Location);
                }
                schemaSet.Compile();
                manifest.SchemaSet = schemaSet;
                //CID 0611 //2010.06.04 //End
            }
            catch (Exception e)
            {
                if (e.InnerException != null && e.InnerException is XmlSchemaException)
                {
                    throw e.InnerException;
                }
                else
                {
                    throw e;
                }
            }
		}
		//CID 0422 //2009.10.14 //End

        // Erucy: Add to Xml Schema Collection
        private static void addToSchemaCollection(XmlSchemaCollection schemaCollection, string ns, CABFile cabFile)
        {
            MemoryStream stream = new MemoryStream(cabFile.ByteOutput);
            XmlTextReader reader = new XmlTextReader(stream);
            schemaCollection.Add(ns, reader);
        }

		//CID 0231 //2009.02.19 //Begin
        //updated by erucy
		private static void buildCollection2(Manifest manifest)
		{
			XmlSchemaCollection schemaCollection = new XmlSchemaCollection();

			//schemaCollection.Add( null, manifest.RootSchemaDef.CabFile.TempFile );
            addToSchemaCollection(schemaCollection, null, manifest.RootSchemaDef.CabFile);

			foreach( SchemaDef schemaDef in manifest.SchemaDefList )
			{
                //schemaCollection.Add( null, schemaDef.CabFile.TempFile );
                addToSchemaCollection(schemaCollection, null, schemaDef.CabFile);
			}

			manifest.SchemaCollection = schemaCollection;
		}
		//CID 0231 //2009.02.19 //End

		//构造SchemaCollection。
		private static void buildCollection1(Manifest manifest)
		{
			SchemaEntityResolver schemaEntityResolver = new SchemaEntityResolver( manifest );
			XmlSchemaCollection schemaCollection = new XmlSchemaCollection();
			
			//编译主Schema.
			SchemaDef rootSchemaDef = manifest.RootSchemaDef;
			StreamReader reader = new StreamReader( new MemoryStream( rootSchemaDef.CabFile.ByteOutput ) );
			XmlSchema schema = XmlSchema.Read( reader , null );
			schema.Compile( null, schemaEntityResolver );
			schemaCollection.Add( schema );

			//将主Schema添加到已经解析的SchemaLink中，因为主Schema可能在SchemaDefList中被重复定义，如QuestionsForm.xsn。
			schemaEntityResolver.addResolvedSchemaLink( rootSchemaDef.SchemaLink );
			
			//编译其它在Manifest中定义的schema。
			foreach( SchemaDef schemaDef in manifest.SchemaDefList )
			{
				if( !schemaEntityResolver.isResolvedSchema( schemaDef.Location ) )
				{
					//删除Schema中已经加入Collection的Import。
					byte[] formatedContent = SchemaUnlinkWorker.removeResolvedImport( schemaDef, schemaCollection );
					reader = new StreamReader( new MemoryStream( formatedContent ) );
					schema = XmlSchema.Read( reader , null );
					schema.Compile( null, schemaEntityResolver );
					schemaCollection.Add( schema );
					//将加入Collection中的Schema加入ResolvedSchemaList。
					schemaEntityResolver.addResolvedSchemaLink( schemaDef.SchemaLink );
				}
			}

			manifest.SchemaCollection = schemaCollection;
		}

	}
}